using B.S.Medical.Api.Read.Application.Command.Payment;
using B.S.Medical.Domain.Doctor;
using B.S.Medical.Domain.Department;
using B.S.Medical.Domain.Medical;
using B.S.Medical.Domain.Payment;
using B.S.Medical.ErrorCode;
using B.S.Medical.Infrastructure.Interface;
using MediatR;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace B.S.Medical.Api.Read.Application.Handler.Payment
{
    /// <summary>
    /// 查询患者已缴费项目处理器
    /// </summary>
    public class GetPaidPaymentItemsHandler : IRequestHandler<GetPaidPaymentItemsCommand, ApiResult<PatientPaidItemsDto>>
    {
        private readonly IBaseRepository<PaymentRecordModel> _paymentRecordRepository;
        private readonly IBaseRepository<PatientModel> _patientRepository;
        private readonly IBaseRepository<PatientBalance> _patientBalanceRepository;
        private readonly IBaseRepository<DoctorModel> _doctorRepository;
        private readonly IBaseRepository<ManageModel> _departmentRepository;
        private readonly ILogger<GetPaidPaymentItemsHandler> _logger;

        /// <summary>
        /// 构造函数
        /// </summary>
        public GetPaidPaymentItemsHandler(
            IBaseRepository<PaymentRecordModel> paymentRecordRepository,
            IBaseRepository<PatientModel> patientRepository,
            IBaseRepository<PatientBalance> patientBalanceRepository,
            IBaseRepository<DoctorModel> doctorRepository,
            IBaseRepository<ManageModel> departmentRepository,
            ILogger<GetPaidPaymentItemsHandler> logger)
        {
            _paymentRecordRepository = paymentRecordRepository;
            _patientRepository = patientRepository;
            _patientBalanceRepository = patientBalanceRepository;
            _doctorRepository = doctorRepository;
            _departmentRepository = departmentRepository;
            _logger = logger;
        }

        /// <summary>
        /// 处理查询患者已缴费项目命令
        /// </summary>
        public async Task<ApiResult<PatientPaidItemsDto>> Handle(GetPaidPaymentItemsCommand request, CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation($"开始查询患者ID为 {request.PatientId} 的已缴费项目");

                // 查询患者信息
                var patient = _patientRepository.GetAll()
                    .Where(p => p.Id == request.PatientId && !p.IsDeleted)
                    .FirstOrDefault();

                if (patient == null)
                {
                    _logger.LogWarning($"未找到患者: {request.PatientId}");
                    return new ApiResult<PatientPaidItemsDto>
                    {
                        Code = ApiEnum.Fail,
                        Msg = "未找到患者信息",
                    };
                }

                // 查询患者余额
                var balance = _patientBalanceRepository.GetAll()
                    .Where(b => b.PatientId == request.PatientId && !b.IsDeleted)
                    .FirstOrDefault();

                decimal cardBalance = balance?.Balance ?? 0;

                // 查询已缴费记录
                var paymentRecords = _paymentRecordRepository.GetAll()
                    .Where(p => p.PatientId == request.PatientId && !p.IsDeleted && p.IsPaid)
                    .OrderByDescending(p => p.PayTime)
                    .ToList();

                // 获取相关医生和科室信息
                var doctorIds = paymentRecords.Select(p => p.DoctorId).Distinct().ToList();
                var doctors = _doctorRepository.GetAll()
                    .Where(d => doctorIds.Contains(d.Id) && !d.IsDeleted)
                    .ToDictionary(d => d.Id, d => d);

                // 获取医生关联的科室ID
                var departmentIds = new List<int>();
                foreach (var doctor in doctors.Values)
                {
                    // 假设DepartmentId是int类型，不是可空类型
                    if (doctor.DepartmentId > 0)
                    {
                        departmentIds.Add(doctor.DepartmentId);
                    }
                }

                var departments = departmentIds.Count > 0 ? 
                    _departmentRepository.GetAll()
                        .Where(d => departmentIds.Contains(d.Id) && !d.IsDeleted)
                        .ToDictionary(d => d.Id, d => d) :
                    new Dictionary<int, ManageModel>();

                // 构建返回结果
                var result = new PatientPaidItemsDto
                {
                    PatientId = patient.Id,
                    PatientName = patient.Name,
                    IdCard = patient.IdCard,
                    PhoneNumber = patient.Phone,
                    CardBalance = cardBalance,
                    PaidItems = new List<PaidItemDto>()
                };

                // 填充已缴费项目
                foreach (var record in paymentRecords)
                {
                    var doctor = doctors.GetValueOrDefault(record.DoctorId);
                    
                    // 获取科室信息
                    ManageModel department = null;
                    if (doctor != null && doctor.DepartmentId > 0)
                    {
                        departments.TryGetValue(doctor.DepartmentId, out department);
                    }

                    result.PaidItems.Add(new PaidItemDto
                    {
                        Id = record.Id,
                        OrderNo = record.OrderNo,
                        ItemName = record.ItemName,
                        DepartmentName = department?.DepartmentName ?? "未知科室",
                        DoctorName = doctor?.DoctorName ?? "未知医生",
                        Amount = record.Amount,
                        PayType = record.PayType ?? "未知",
                        PayStatus = record.PayStatus ?? "已支付",
                        PayTime = record.PayTime,
                        CreatedTime = record.CreatedTime
                    });
                }

                _logger.LogInformation($"查询到患者 {patient.Name}({patient.Id}) 的已缴费项目 {result.PaidItems.Count} 条");

                return new ApiResult<PatientPaidItemsDto>
                {
                    Code = ApiEnum.Success,
                    Msg = "查询成功",
                    Data = result
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"查询患者已缴费项目失败: PatientId={request.PatientId}, Error={ex.Message}");
                return new ApiResult<PatientPaidItemsDto>
                {
                    Code = ApiEnum.Error,
                    Msg = $"查询患者已缴费项目失败: {ex.Message}"
                };
            }
        }
    }
} 